/**
 * 
 */
package com.zaodei.rxjob.job.controller;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zaodei.rxjob.common.annotation.Log;
import com.zaodei.rxjob.common.base.AjaxResult;
import com.zaodei.rxjob.common.enums.BusinessType;
import com.zaodei.rxjob.common.page.TableDataInfo;
import com.zaodei.rxjob.core.util.ShiroUtils;
import com.zaodei.rxjob.core.web.base.BaseController;
import com.zaodei.rxjob.job.admin.core.model.JobGroupProject;
import com.zaodei.rxjob.job.admin.core.model.XxlJobGroup;
import com.zaodei.rxjob.job.admin.core.model.XxlJobInfo;
import com.zaodei.rxjob.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.zaodei.rxjob.job.admin.core.thread.JobTriggerPoolHelper;
import com.zaodei.rxjob.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
import com.xxl.job.core.glue.GlueTypeEnum;
import com.zaodei.rxjob.job.dao.ProjectJobGroupdao;
import com.zaodei.rxjob.job.dao.XxlJobGroupDao;
import com.zaodei.rxjob.job.service.NXxlJobService;

/**
 * 
 * @Title:任务
 * @Description:对任务进行管理
 * @Author:wuche@laozo.com
 * @time:2019年1月17日
 */
@Controller
@RequestMapping("/job/jobinfo")
public class NjobInfoController extends BaseController {
	private String prefix = "job/jobinfo";
	@Resource
	private XxlJobGroupDao xxlJobGroupDao;
	@Resource
	private NXxlJobService xxlJobService;
	
	@Resource
	private ProjectJobGroupdao projectJobGroupdao;

	@RequiresPermissions("job:jobinfo:view")
	@GetMapping()
	public String jobinfo(Model model) {
		model.addAttribute("GlueTypeEnum", GlueTypeEnum.values()); // Glue类型-字典
		// 任务组
		//List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
		XxlJobGroup jobGroup = new XxlJobGroup();
		jobGroup.setUserId(getUserId());
		List<XxlJobGroup> jobGroupList = xxlJobGroupDao.selectJobGroupList(jobGroup);
		model.addAttribute("JobGroupList", jobGroupList);
		return prefix + "/jobinfo";
	}

	// @RequiresPermissions("job:jobinfo:list")
	@RequiresPermissions("job:jobinfo:view")
	@RequestMapping("/list")
	@ResponseBody
	public TableDataInfo list(XxlJobInfo jobInfo) {
		startPage();
		jobInfo.setUserId(ShiroUtils.getUserId());
		List<XxlJobInfo> jobinfoList = xxlJobService.selectJobInfoList(jobInfo);
		return getDataTable(jobinfoList);
	}

	/**
	 * 新增任务
	 */
	@RequiresPermissions("job:jobinfo:add")
	@GetMapping("/add")
	public String add(ModelMap mmap) {
		getModelMap(mmap);
		// 任务组
		//List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
		XxlJobGroup jobGroup = new XxlJobGroup();
		jobGroup.setUserId(getUserId());
		List<XxlJobGroup> jobGroupList = xxlJobGroupDao.selectJobGroupList(jobGroup);
		mmap.addAttribute("JobGroupList", jobGroupList);
		return prefix + "/add";
	}

	@RequiresPermissions("job:jobinfo:add")
	@Log(title = "新增调度任务", businessType = BusinessType.INSERT)
	@Transactional(rollbackFor = Exception.class)
	@PostMapping("/add")
	@ResponseBody
	public AjaxResult add(XxlJobInfo jobInfo) {
		return xxlJobService.add(jobInfo);
	}

	/**
	 * 更新任务
	 */
	@RequiresPermissions("job:jobinfo:edit")
	@GetMapping("/edit/{id}")
	public String edit(ModelMap mmap, @PathVariable("id") int id) {
		getModelMap(mmap);
		// 任务组
		XxlJobGroup jobGroup = new XxlJobGroup();
		jobGroup.setUserId(getUserId());
		List<XxlJobGroup> jobGroupList = xxlJobGroupDao.selectJobGroupList(jobGroup);
	//	List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
		mmap.addAttribute("JobGroupList", jobGroupList);
		mmap.addAttribute("jobInfo", xxlJobService.loadJobInfo(id));
		return prefix + "/edit";
	}

	@RequiresPermissions("job:jobinfo:edit")
	@Log(title = "修改调度任务", businessType = BusinessType.UPDATE)
	@RequestMapping("/edit")
	@Transactional(rollbackFor = Exception.class)
	@ResponseBody
	public AjaxResult edit(XxlJobInfo jobInfo) {
		// 添加操作控制
		XxlJobInfo xxlJobInfo = xxlJobService.loadJobInfo(jobInfo.getId());
		if (!isOptJob(xxlJobInfo.getJobGroup())) {
			return error("观察者没有操作权限");
		}
		return xxlJobService.update(jobInfo);
	}

	@RequiresPermissions("job:jobinfo:remove")
	@Log(title = "删除调度任务", businessType = BusinessType.DELETE)
	@RequestMapping("/remove")
	@ResponseBody
	public AjaxResult remove(String ids) {
		int id = 0;
		if (StringUtils.isNotEmpty(ids)) {
			id = Integer.parseInt(ids);
			XxlJobInfo xxlJobInfo = xxlJobService.loadJobInfo(id);
			// 添加操作控制
			if (!isOptJob(xxlJobInfo.getJobGroup())) {
				return error("观察者没有操作权限");
			}
		} else {
			return error("删除任务不存在");
		}
		return xxlJobService.remove(id);
	}

	@RequiresPermissions("job:jobinfo:view")
	@Log(title = "暂停调度任务", businessType = BusinessType.FORCE)
	@RequestMapping("/stop")
	// TODO, pause >> stop
	@ResponseBody
	public AjaxResult pause(@RequestParam Map<String, Object> paramMap) {
		String ids = (String) paramMap.get("id");
		int id = 0;
		if (StringUtils.isNotEmpty(ids)) {
			id = Integer.parseInt(ids);
			XxlJobInfo xxlJobInfo = xxlJobService.loadJobInfo(id);
			// 添加操作控制
			if (!isOptJob(xxlJobInfo.getJobGroup())) {
				return error("观察者没有操作权限");
			}
		} else {
			return error("停止任务不存在");
		}
		return xxlJobService.stop(id);
	}

	@RequiresPermissions("job:jobinfo:view")
	@Log(title = "启动调度任务", businessType = BusinessType.UPDATE)
	@RequestMapping("/start")
	@ResponseBody
	public AjaxResult start(@RequestParam Map<String, Object> paramMap) {
		String ids = (String) paramMap.get("id");
		int id = 0;
		if (StringUtils.isNotEmpty(ids)) {
			id = Integer.parseInt(ids);
			XxlJobInfo xxlJobInfo = xxlJobService.loadJobInfo(id);
			// 添加操作控制
			if (!isOptJob(xxlJobInfo.getJobGroup())) {
				return error("观察者没有操作权限");
			}
		} else {
			return error("启动任务不存在");
		}
		return xxlJobService.start(id);
	}

	/**
	 * 执行
	 */
	@RequiresPermissions("job:jobinfo:view")
	@GetMapping("/trigger/{id}")
	public String trigger(Model mmap, @PathVariable("id") int id) {
		mmap.addAttribute("id", id);
		return prefix + "/trigger";
	}

	@RequiresPermissions("job:jobinfo:view")
	@RequestMapping("/trigger")
	@ResponseBody
	public AjaxResult triggerJob(@RequestParam Map<String, Object> paramMap) {
		String executorParam = (String) paramMap.get("executorParam");
		// force cover job param
		if (executorParam == null) {
			executorParam = "";
		}
		String ids = (String) paramMap.get("id");
		int id = 0;
		if (StringUtils.isNotEmpty(ids)) {
			id = Integer.parseInt(ids);
			XxlJobInfo xxlJobInfo = xxlJobService.loadJobInfo(id);
			// 添加操作控制
			if (!isOptJob(xxlJobInfo.getJobGroup())) {
				return error("观察者没有操作权限");
			}
		} else {
			return error("执行任务不存在");
		}
		JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null,
				executorParam);
		return toAjax(true);
	}

	private void getModelMap(ModelMap mmap) {
		// 枚举-字典
		mmap.addAttribute("ExecutorRouteStrategyEnum",
				ExecutorRouteStrategyEnum.values()); // 路由策略-列表

		mmap.addAttribute("GlueTypeEnum", GlueTypeEnum.values()); // Glue类型-字典
		mmap.addAttribute("ExecutorBlockStrategyEnum",
				ExecutorBlockStrategyEnum.values()); // 阻塞处理策略-字典
		// 任务组
		List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
		mmap.addAttribute("JobGroupList", jobGroupList);
	}

	// 判断用户是否可以进行操作
	private boolean isOptJob(int id) {
		JobGroupProject jobGroupProject = new JobGroupProject();
		jobGroupProject.setJobGroup(id);
		jobGroupProject.setUserId(ShiroUtils.getUserId());
		jobGroupProject = projectJobGroupdao.selectProjectJobGroupUser(jobGroupProject);
		Long roleId = jobGroupProject.getRoleId();
		boolean isOpt = false;
		if (6 == roleId || 4 == roleId) {
			isOpt = true;
		}
		return isOpt;
	}
}
